using System;
using CI.Misc;
using NUnit.Framework;
using CI;
using CI.Interfaces;
using CI.Organism;

namespace Mesopotamia.UnitTests
{
    /// <summary>MSRB hosting environment Unit Testing</summary>
    [TestFixture]
    public class MSRBHostTests
    {
        private IHostingEnvironment _msrbhost;
        private OrganismCollection _organisms;
        private IOrganism _organism;

        [SetUp]
        public void Setup()
        {
            // reset
            _msrbhost = new CI.Mesopotamia.MSRBHost(new MockHostingEnvironmentPhysical(), new CI.Mesopotamia.ScenarioLocalXML());
            _organism = new CI.Organism.Organism(_msrbhost);
            _organisms = new OrganismCollection();

            // set an timespan for all the organisms
            _msrbhost.HBOrganismCollectionMin = new TimeSpan();
            // create a collection of organisms
            _msrbhost.Organisms = _organisms;
            // clear break flag
            SimEnv.Instance.ClearBreakFlag();
            
             // set alive organisms
            _msrbhost.Organisms.AliveAdd(_organism);

            // set the dead organisms
            _msrbhost.Organisms.Dead.Clear();
        }

        [Test, ExpectedException(typeof(ArgumentException), ExpectedMessage = "hostingEnvironmentPhysical")]
        public void CtorNullhostingEnvironmentPhysicalArgumentException()
        {
            // create with a null physical hosting environment
            _msrbhost = new CI.Mesopotamia.MSRBHost(null, new CI.Mesopotamia.ScenarioLocalXML());
        }


        [Test, ExpectedException(typeof(ArgumentException), ExpectedMessage="Organisms")]
        public void StartNullOrganismsArgumentException()
        {
            // clear the organisms
            _msrbhost.Organisms = null;
            // start the process
            _msrbhost.Start();
        }

        [Test, ExpectedException(typeof(ArgumentException), ExpectedMessage="Organisms.Alive")]
        public void StartNullOrganismsAliveArgumentException()
        {
            // clear the organisms
            _msrbhost.Organisms.Alive = null;
            // start the process
            _msrbhost.Start();
        }

        [Test, ExpectedException(typeof(ArgumentException), ExpectedMessage = "Organisms.Dead")]
        public void StartNullOrganismsDeadArgumentException()
        {
            // clear the organisms
            _msrbhost.Organisms.Dead = null;
            // start the process
            _msrbhost.Start();
        }

        ///// <summary>
        ///// check and make sure if we call start with break set it will break with out executing any of the code        
        ///// </summary>
        //[Test,Ignore]
        //public void StartBreakExitFalseTrue()
        //{
        //    // mock the organisms alive collection childOrganism as we will check them to see if they were called as they come after break exit
        //    _organism = _mocks.DynamicMock<CI.Organism.Organism>(_msrbhost);
        //    _msrbhost.FitnessFunction = _mocks.DynamicMock<IFitnessFunction>();
        //    _organism.NeuralSystem = new CI.Organism.SimpleNeuralSystem(_organism);
        //    _organism.DNA = _mocks.DynamicMock<IDNA>();
            
        //    // now add our mocked one
        //    _organisms.AliveAdd(_organism);
     
        //    // set the break flag
        //    _msrbhost.BreakExit = true;

        //    // record what i expect to happen
        //    using (_mocks.Record())
        //    {
        //        Expect.Call(_organism.Heartbeat).Repeat.Never();
        //    }

        //    // playback
        //    using (_mocks.Playback())
        //    {
        //        _msrbhost.Start();
        //    }

        //}
            
        ///// <summary>
        ///// // check and make sure Heartbeat gets called in start method
        ///// </summary>
        //[Test,Ignore]
        //public void StartHeartbeatTrue()
        //{            
        //    // mock the what we need
        //    _msrbhost.FitnessFunction = _mocks.DynamicMock<IFitnessFunction>();
        //    _organism.NeuralSystem = new CI.Organism.SimpleNeuralSystem(_organism);
        //    _organism.DNA = _mocks.DynamicMock<IDNA>();

        //    // now add our mocked objects
        //    _organisms.AliveAdd(_organism);

        //    // record what i expect to happen
        //    using (_mocks.Record())
        //    {
        //        Expect.Call(_organism.Heartbeat).Do(new SetBreakExit(SetBreakExitTrue));                
        //    }

        //    using (_mocks.Playback())
        //    {
        //        _msrbhost.Start();
        //    }

        //}
                
        // delegate to set break exit, empty
        delegate void SetBreakExit();
        private void SetBreakExitTrue ()
        {
            SimEnv.Instance.TriggerScenarioRestart("test");
        }
        // delegate to set break exit, organisms
        delegate void SetBreakExitOrganismCollection(IOrganismCollection organisms);
        private void SetBreakExitTrueOrganismCollection(IOrganismCollection organisms)
        {
            SimEnv.Instance.TriggerScenarioRestart("test");
        }

    }
}
